package com.itboye.ihomebank.net;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.Spanned;
import android.util.Log;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.NoConnectionError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.itboye.ihomebank.base.MyApplcation;
import com.itboye.ihomebank.constants.SPContants;
import com.itboye.ihomebank.util.ByAlert;
import com.itboye.ihomebank.util.DebugLog;
import com.itboye.ihomebank.util.SPUtils;
import com.itboye.ihomebank.util.String2Spanned;
import com.orhanobut.logger.Logger;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;


/**
 * 建造者模式创建Request  
 * .默认请求 DEPRECATED_GET_OR_POST
 * 
 * @author w
 *
 * @param <T> 请求结束后返回的对象，可以是 List<自定义类>  或  自定义类  
 */
public class XJsonRequest<T> extends Request<T> {

	private Type expectReturnType;//期望返回参数的类
	private XRequestListener<T> listener;
	
	private XErrorListener errorListener;
	private Map<String,String>headers=new HashMap<String, String>();
	private  int method=Method.DEPRECATED_GET_OR_POST;
	private Map<String,String>params=new HashMap<String, String>();
	
	/**
	 * 处理code！=0时的特殊情况！！！！！！
	 * 
	 */
	private boolean isCodeZero=true;
	/**
	 * 
	 * 
	 * @param
	 * @param url
	 * @param listener
	 * @param errlistener  请求异常，失败，code！=0 时会调用，</br></br>
	 * code!=0时，onErrorResponse(Exception exception,int code,String msg)中
	 * exception 是CodeErrorException，code为服务器返回的状态码，msg为服务端返回的出错信息（data中字符串）
	 * </br></br>
	 * json解析失败时，onErrorResponse(Exception exception,int code,String msg)中
	 * exception 是JSONException，code为0，msg为null
	 * </br></br>
	 * 其他异常时 onErrorResponse(Exception exception,int code,String msg)中
	 * exception 是Exception，code为0，msg为null
	 */
	public XJsonRequest(String url, XRequestListener<T> listener, XErrorListener errlistener) {
		
		super(Method.POST,url, null);
		this.listener = listener;
		this.errorListener=errlistener;
	}
	
	/**
	 * 
	 * @param method
	 * @param url
	 * @param listener
	 * @param errlistener  请求异常，失败，code！=0 时会调用，</br></br>
	 * code!=0时，onErrorResponse(Exception exception,int code,String msg)中
	 * exception 是CodeErrorException，code为服务器返回的状态码，msg为服务端返回的出错信息（data中字符串）
	 * </br></br>
	 * json解析失败时，onErrorResponse(Exception exception,int code,String msg)中
	 * exception 是JSONException，code为0，msg为null
	 * </br></br>
	 * 其他异常时 onErrorResponse(Exception exception,int code,String msg)中
	 * exception 是Exception，code为0，msg为null
	 */
	public XJsonRequest(int method,String url, XRequestListener<T> listener, XErrorListener errlistener) {
		
		super(method, url, null);
		
		this.listener = listener;
		this.errorListener=errlistener;
	}

	
	@Override
	protected void deliverResponse(T response) {
		if (null != listener) {
			try {
				listener.onResponse(response);
			} catch (Exception e) {
				
				e.printStackTrace();
			}
		}
	}
	
	@Override
	public void deliverError(VolleyError error) {
		super.deliverError(error);

		if (errorListener !=null && isCodeZero) {
			try {
				if(error instanceof NoConnectionError){
                    NoConnectionError error1 = (NoConnectionError) error;

					String msg = "网络连接异常，请检查网络...";
                    errorListener.onErrorResponse(error1, "0", msg);
				} else if(error instanceof TimeoutError||error instanceof ServerError){
					if (error instanceof TimeoutError){
						TimeoutError jsonException=(TimeoutError) error;
						String msg = "服务器异常";
						errorListener.onErrorResponse(jsonException, "0", msg);
					}else {
						ServerError jsonException=(ServerError) error;
						String msg = "服务器异常";
						errorListener.onErrorResponse(jsonException, "0", msg);
					}

				}
				else if(error instanceof VolleyError){
                    errorListener.onErrorResponse(error, "0", error.getMessage());
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	}
	public XJsonRequest<T>addHeader(String k,String value){
		headers.put(k, value);
		return this;
	}
	
	@Override
	public Map<String, String> getHeaders() throws AuthFailureError {
		return  headers;
	}
	
	public XJsonRequest<T>setMethod(int method){
		this.method=method;
		return this;
	}
	
	@Override
	public int getMethod() {
		return  method;
	}
	
	public XJsonRequest<T>addParam(String k,String value){

		params.put(k, value);
		return this;
	}
	public XJsonRequest<T>addParams(Map<String,String>params){
		this.params.putAll(params);
		return this;
	}
	
	@Override
	protected Map<String, String> getParams() throws AuthFailureError {
		
		return  params;
	}
	
	
	public Type getExpectReturnType() {
		return expectReturnType;
	}

	public void setExpectReturnType(Type expectReturnType) {
		this.expectReturnType = expectReturnType;
		
	}
	
	//该方法中gson解析可能需要调整
	@Override
	protected Response<T> parseNetworkResponse(NetworkResponse response) {

		String parsed;
		try {
			parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
		} catch (UnsupportedEncodingException e) {
			parsed = new String(response.data);
		}

		try {
			if (listener == null) {
				return null;
			}

			JSONObject obj  = new JSONObject(parsed);
			if (parsed.contains("code")){

                String type = obj.getString("type");
                String resultData = obj.getString("data");
                String code = obj.getString("code");
                if(type.equals("E")){
                    Log.d("request_params", "服务器出错!"+type);
                    return  Response.error(new VolleyError("服务器出错!"));
                }

                if(this.getExpectReturnType() == null){
                    Log.d("request_params", "必须指定返回数据类型"+this.getExpectReturnType());
                    return  Response.error(new VolleyError("必须指定返回数据类型"));
                }

                resultData = DataEncryptionUtil.decodeData(resultData);

                if (!code.equals("0")) {
                    if (errorListener!=null) {
                        String data = obj.getString("data");
                        if(data != null){
                            Log.d("request_params", "-------------------------------------请求失败----------------------------1!"+data);
                            handlerError(new CodeErrorException(data), code,data);
                        }else{
                            Log.d("request_params", "-----------------------------------------请求失败-------------------------------2"+data);
                            handlerError(new CodeErrorException("请求失败!"), code,data);
                        }
                    }
                    if (!"".equals(SPUtils.get(MyApplcation.ctx,null,SPContants.LOCK_SESSION,"")+"")&&code.equals("1111")){ //备用锁session 过期

//						SPUtils.put(MyApplcation.ctx,null,SPContants.LOCK_SESSION,"");
						return  Response.error(new VolleyError("网络连接错误,请重试..."));
					}
                    return  Response.error(new VolleyError("请求异常!"));
                }

                Logger.json(resultData);
                Gson gson = new GsonBuilder()
                        .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                        .registerTypeAdapter(Spanned.class, new String2Spanned())
                        .create();
                if(resultData.contains("操作成功,非低电量")) {
                    resultData="操作成功" ;
                }
                if(resultData.contains("操作成功:")) {
                    resultData="操作成功" ;
                }
                @SuppressWarnings("unchecked")
                T res = (T) gson.fromJson(resultData, this.expectReturnType);
                Log.d("request_params", "实体类类型："+res.getClass().toString());
                Log.d("request_params", "--------------------------------------------请求结束-------------------------------------------------");
                if (null != res) {
                    return Response.success(res, HttpHeaderParser.parseCacheHeaders(response));

                }


            }else {

                String type = obj.getString("type");
                String resultData = obj.getString("data");
                if(type.equals("E")){
                    Log.d("request_params", "服务器出错!"+type);
                    return  Response.error(new VolleyError("服务器出错!"));
                }

                if(this.getExpectReturnType() == null){
                    Log.d("request_params", "必须指定返回数据类型"+this.getExpectReturnType());
                    return  Response.error(new VolleyError("必须指定返回数据类型"));
                }

//			Type typeClass1 = listener.getClass().getGenericSuperclass();
//			if (!(typeClass1 instanceof ParameterizedType) ){
//				return  Response.error(new VolleyError("返回参数异常!"));
//			}
//
//			Type actualType = ((ParameterizedType) typeClass1).getActualTypeArguments()[0];


                parsed = DataEncryptionUtil.decodeData(resultData);

                JSONObject decodeJsonObj = new JSONObject(parsed);
                String code = decodeJsonObj.getString("code");
                if (!code.equals("0")) {
                    if (errorListener!=null) {
                        String data = decodeJsonObj.getString("data");
                        if(data != null){
                            Log.d("request_params", "-------------------------------------请求失败----------------------------1!"+data);
                            handlerError(new CodeErrorException(data), code,data);
                        }else{
                            Log.d("request_params", "-----------------------------------------请求失败-------------------------------2"+data);
                            handlerError(new CodeErrorException("请求失败!"), code,data);
                        }

                    }
					if (!"".equals(SPUtils.get(MyApplcation.ctx,null,SPContants.LOCK_SESSION,"")+"")&&code.equals("1111")){ //备用锁session 过期

//						SPUtils.put(MyApplcation.ctx,null,SPContants.LOCK_SESSION,"");
						return  Response.error(new VolleyError("网络连接错误,请重试..."));
					}
                    return  Response.error(new VolleyError("请求异常!"));
                }

                resultData = decodeJsonObj.getString("data");
                Logger.json(resultData);
                Gson gson = new GsonBuilder()
                        .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                        .registerTypeAdapter(Spanned.class, new String2Spanned())
                        .create();
                if(resultData.contains("操作成功,非低电量")) {
                    resultData="操作成功" ;
                }
                if(resultData.contains("操作成功:")) {
                    resultData="操作成功" ;
                }
                @SuppressWarnings("unchecked")
                T res = (T) gson.fromJson(resultData, this.expectReturnType);
                Log.d("request_params", "实体类类型："+res.getClass().toString());
                Log.d("request_params", "--------------------------------------------请求结束-------------------------------------------------");
                if (null != res) {
                    return Response.success(res, HttpHeaderParser.parseCacheHeaders(response));

                }
            }


		} catch (JSONException e) {
//			return Response.success(res, HttpHeaderParser.parseCacheHeaders(response));
			e.printStackTrace();
		}
		return  Response.error(new VolleyError("请求异常!"));
		
	}
	
	/**
	 * 输出完整json，防止一次输出过多时显示不完整问题
	 * @param tag
	 * @param json
	 */
	private void printLogDetail(String tag, String json) {
		
		try {
			int len=3500;
			int position=0;
			
			while(json.length()-position>len){
				for (int i = 0; i < json.length()-position-len; i++) {
					if (json.charAt(position+len+i)=='\n') {
						DebugLog.v(tag, json.substring( position,position+len+i ));

						position=position+len+i+1;
						break;
					}
				}
				
			}
			DebugLog.v(tag, json.substring( position,json.length()));

		} catch (Exception e) {
			DebugLog.v(tag, json);
		}
		
	}

	private void handlerError(final Exception exception,final String code,final String msg){
		
		isCodeZero=false;
//		errorListener.onErrorResponse(exception, code, msg);

		new Handler(Looper.getMainLooper()){
			@Override
			public void handleMessage(Message m) {
				errorListener.onErrorResponse(exception, code, msg);
				super.handleMessage(m);
				try {
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			
		}.sendEmptyMessage(0);
		

	}

}
